package com.stars.module.login.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.stars.base.constants.CommonNumberConstants;
import com.stars.base.constants.RedisConstants;
import com.stars.base.constants.SystemSettingConstants;
import com.stars.base.entity.SessionUser;
import com.stars.base.exception.BaseException;
import com.stars.module.department.entity.StarDept;
import com.stars.module.department.service.StarDeptService;
import com.stars.module.log.entity.LogEnum;
import com.stars.module.log.service.StarLogService;
import com.stars.module.login.service.LoginService;
import com.stars.module.privilege.service.StarPrivilegeService;
import com.stars.module.role.service.StarRoleService;
import com.stars.module.user.entity.StarUser;
import com.stars.module.user.mapper.UserMapper;
import com.stars.util.cache.CacheUtil;
import com.stars.util.common.DevelopKit;
import com.stars.util.ecrypt.MD5Util;
import com.stars.util.jwt.JWTUtil;
import org.apache.shiro.SecurityUtils;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author : Rocks
 * @version : 1.0
 * @date : 2022/10/18 10:04
 * @description : 登录服务实现类
 */
@Service
public class LoginServiceImpl implements LoginService {

    private final UserMapper userMapper;
    private final StarLogService logService;
    private final StarDeptService deptService;
    private final StarRoleService roleService;
    private final StarPrivilegeService privilegeService;
    private final CacheUtil cacheUtil;

    public LoginServiceImpl(UserMapper userMapper, StarLogService logService, StarDeptService deptService, StarRoleService roleService, StarPrivilegeService privilegeService, CacheUtil cacheUtil) {
        this.userMapper = userMapper;
        this.logService = logService;
        this.deptService = deptService;
        this.roleService = roleService;
        this.privilegeService = privilegeService;
        this.cacheUtil = cacheUtil;
    }

    @Override
    public SessionUser doLogin(String logName, String password) throws BaseException {

        LambdaQueryWrapper<StarUser> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.eq(StarUser::getLogName,logName);

        StarUser user = userMapper.selectOne(queryWrapper);
        if(user==null){
            return null;
        }
        //对密码加密
        password = MD5Util.md5(password);
        if(!password.equals(user.getPassword())){
            return null;
        }

        String config = DevelopKit.getStringFromDBConfig(SystemSettingConstants.SYS_ALLOW_SINGLE, CommonNumberConstants.ZERO_STR);
        // 判断当前用户是否已经登录,如果已经登录则将上一个登录信息踢下线，暂不考虑多端登录
        List<String> tempSessionList = Optional.ofNullable(cacheUtil.getValueByList(false, RedisConstants.SESSION_USER_PREFIX+user.getId(), String.class)).orElseGet(ArrayList::new);

        if (CommonNumberConstants.ONE_STR.equals(config) && !tempSessionList.isEmpty()) {

            for (String tempSessionId : tempSessionList) {
                SessionUser tempUser = cacheUtil.getValue(false, RedisConstants.SESSION_PREFIX + tempSessionId, SessionUser.class);

                if (tempUser != null) {
                    cacheUtil.clearCache(false, RedisConstants.SESSION_PREFIX + tempSessionId);
                }
            }

            cacheUtil.clearCache(false, RedisConstants.SESSION_USER_PREFIX+user.getId());
        }

        user.setLastLoginTime(new Date());

        userMapper.updateById(user);
        logService.saveLog(LogEnum.LOGIN,"用户登录");

        SessionUser sessionUser = this.initUser(user);

        String sessionId = DevelopKit.generateUUID();

        String token = JWTUtil.generateToken(sessionId);
        sessionUser.setToken(token);

        String onLineTime = DevelopKit.getStringFromDBConfig(SystemSettingConstants.SYS_ONLINE_TIME, RedisConstants.DEFAULT_ONLINE);

        cacheUtil.setValue(false,RedisConstants.SESSION_PREFIX+sessionId, sessionUser , Long.parseLong(onLineTime));

        tempSessionList.add(sessionId);

        cacheUtil.setValue(false,RedisConstants.SESSION_USER_PREFIX+sessionUser.getUserId(), tempSessionList , Long.parseLong(onLineTime));

        return sessionUser;
    }

    @Override
    public void logout() {
        String sessionId = (String) SecurityUtils.getSubject().getPrincipal();
        cacheUtil.delKey(false,RedisConstants.SESSION_PREFIX+sessionId);
    }

    private SessionUser initUser (StarUser user) throws BaseException {

        SessionUser sessionUser = new SessionUser(user);

        StarDept mainDept = deptService.loadUserMainDept(user.getId());

        if (mainDept == null) {
            throw new BaseException("当前用户未分配主部门");
        }

        sessionUser.setCurrentDept(mainDept.getId());
        sessionUser.setCurrentDeptName(mainDept.getOrgName());
        sessionUser.setCurrentUnit(mainDept.getUnitId());
        sessionUser.setCurrentUnitName(mainDept.getUnitName());

        String roles = roleService.loadUserRoles(user.getId());
        sessionUser.setRoles(roles);

        String privileges = privilegeService.loadUserPrivileges(user.getId());
        sessionUser.setPrivileges(privileges);

        return sessionUser;
    }
}
